package io.github.ramerf.wind.core.domain;

import com.alibaba.fastjson.JSON;
import io.github.ramerf.wind.core.util.Asserts;
import java.util.*;
import javax.annotation.Nonnull;
import lombok.Getter;
import lombok.Setter;

/**
 * 分页对象.
 *
 * @author ramer
 * @since 2022.02.27
 */
@Getter
public class Page<T> {
  private final List<T> content = new ArrayList<>();

  public static final Page<?> EMPTY =
      Page.of(Collections.emptyList(), PageRequest.of(Integer.MAX_VALUE));

  /** 当前页号,首页为1. */
  private long pageNumber;

  /** 每页数量. */
  private long size;

  /** 总记录数. */
  @Setter private long totalElements;

  /** 总页数. */
  private long totalPages;

  /** 排序规则. */
  private Sort sort;

  private Page() {}

  public static <T> Page<T> of(@Nonnull final List<T> content) {
    return of(content, Pageable.unpaged());
  }

  public static <T> Page<T> of(@Nonnull final List<T> content, final Pageable pageable) {
    return of(content, pageable, 0);
  }

  public static <T> Page<T> of(
      @Nonnull final List<T> content, @Nonnull final Pageable pageable, final long total) {
    Asserts.notNull(content, "Content must not be null!");
    Asserts.notNull(pageable, "Pageable must not be null!");
    Page<T> page = new Page<>();
    page.content.addAll(content);
    page.pageNumber = pageable.isPaged() ? pageable.getPageNumber() : 0;
    page.size = pageable.isPaged() ? pageable.getPageSize() : 0;
    page.totalElements =
        pageable.isPaged()
            ? Optional.of(pageable)
                .filter(o -> !content.isEmpty()) //
                .filter(o -> o.getOffset() + o.getPageSize() > total) //
                .map(o -> o.getOffset() + content.size()) //
                .orElse(total)
            : total;
    page.totalPages =
        page.size == 0 ? 1 : (int) Math.ceil((double) page.totalElements / (double) page.size);
    page.sort = pageable.getSort();
    return page;
  }

  /** 当前页记录数. */
  public int getNumberOfElements() {
    return content.size();
  }

  /** 是否还有上一页. */
  public boolean hasPrevious() {
    return getPageNumber() > 1;
  }

  /** 是否还有下一页. */
  public boolean hasNext() {
    return getPageNumber() < getTotalPages();
  }

  /** 是否最后一页. */
  public boolean isLast() {
    return !hasNext();
  }

  @SuppressWarnings("unchecked")
  public static <T> Page<T> empty() {
    return (Page<T>) EMPTY;
  }

  public static void main(String[] args) {
    System.out.println(" : " + JSON.toJSONString(Page.empty(), true));
  }
}
